package avicit.bdp.dms.perm.service;

import avicit.bdp.common.base.BaseService;
import avicit.bdp.common.service.dao.DatasourcePermDAO;
import avicit.bdp.common.service.dto.DataSourceDTO;
import avicit.bdp.common.service.dto.DatasourcePermDTO;
import avicit.bdp.common.service.service.DataSourceService;
import avicit.bdp.common.utils.BdpLogUtil;
import avicit.bdp.common.utils.CheckParaUtils;
import avicit.bdp.core.constant.Constants;
import avicit.platform6.api.system.SysRoleClient;
import avicit.platform6.api.sysuser.dto.SysRole;
import avicit.platform6.commons.utils.*;
import avicit.platform6.core.context.ThreadContextHelper;
import avicit.platform6.core.exception.BusinessException;
import avicit.platform6.core.properties.PlatformConstant;
import avicit.platform6.core.rest.msg.QueryReqBean;
import avicit.platform6.core.rest.msg.QueryRespBean;
import com.alibaba.fastjson2.JSONObject;
import com.fasterxml.jackson.core.type.TypeReference;
import com.google.common.collect.Lists;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;

/**
 * @金航数码科技有限责任公司 @作者：developer @邮箱：developer@avic-digital.com @创建时间：
 * 2022-11-03 @类说明：DatasourcePermService @修改记录： @注意事项： @主要功能：数据源权限Service
 */
@Service
public class DatasourcePermService extends BaseService<DatasourcePermDAO, DatasourcePermDTO> {
  private static final Logger logger = LoggerFactory.getLogger(DatasourcePermService.class);

  @Autowired private DataSourceService dataSourceService;
  @Autowired
  private SysRoleClient sysRoleClient;

  public QueryRespBean<SysRole> searchSysRoleByPage(QueryReqBean<SysRole> queryReqBean) {
    if (StringUtils.isNotEmpty(queryReqBean.getSidx()) && StringUtils.isNotEmpty(queryReqBean.getSord())) {
      String sordExp = BusinessUtil.getSortExpColumnName(queryReqBean.getSidx(), queryReqBean.getSord(), SysRole.class);
      if (StringUtils.isNotEmpty(sordExp))
        queryReqBean.setSortExp(sordExp);
    }
    if (StringUtils.isNotEmpty(queryReqBean.getKeyWord())) {
      DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
      SysRole searchKeyWordParam = (SysRole)JsonHelper.getInstance().readValue(queryReqBean.getKeyWord(), dateFormat, new TypeReference<SysRole>() {

      });
      if (queryReqBean.getSearchParams() != null && StringUtils.isNotBlank(((SysRole)queryReqBean.getSearchParams()).getRoleGroup()))
        searchKeyWordParam.setRoleGroup(((SysRole)queryReqBean.getSearchParams()).getRoleGroup());
      queryReqBean.setSearchParams(searchKeyWordParam);
    }
    ((SysRole)queryReqBean.getSearchParams()).setSysApplicationId(ThreadContextHelper.getAppId());
    ((SysRole)queryReqBean.getSearchParams()).setOrgIdentity(ThreadContextHelper.getOrgId());

    QueryRespBean<SysRole> result = sysRoleClient.searchSysRoleByPage(queryReqBean);
    return result;
  }

  /**
   * 新增数据源权限
   *
   * @param permList 支持批量授权
   * @return
   */
  @Transactional
  public void addDatasourcePerm(List<DatasourcePermDTO> permList) {
    // step1:合法性检查
    checkAddDatsourcePermValidity(permList);

    // step2:构建权限
    List<DatasourcePermDTO> permDTOList = batchBuildPerm(permList);

    String orgId = ThreadContextHelper.getOrgId();
    if (StringUtils.isBlank(orgId)) {
      orgId = Constants.DEFAULT_ORG;
    }

    // step3:根据roleId+dsId删除老权限
    for (DatasourcePermDTO currPerm : permList) {
      this.mapper.deletePermByCond(currPerm.getRoleId(), currPerm.getDatasourceId(), orgId);
    }

    // step4:元数据持久化
    this.mapper.batchInsertDatasourcePerm(permDTOList);

    // step5:审计日志
    for (DatasourcePermDTO currPerm : permDTOList) {
      BdpLogUtil.log4Insert(currPerm);
    }
  }

  /**
   * 移除数据源权限
   *
   * @param permList
   * @return
   */
  @Transactional
  public void removeDatasourcePerm(List<DatasourcePermDTO> permList) {
    if (CollectionUtils.isEmpty(permList)) {
      return;
    }

    String orgId = ThreadContextHelper.getOrgId();
    if (StringUtils.isBlank(orgId)) {
      orgId = Constants.DEFAULT_ORG;
    }

    for (DatasourcePermDTO currPerm : permList) {
      if (currPerm == null) {
        continue;
      }
      if (StringUtils.isBlank(currPerm.getRoleId())) {
        continue;
      }
      if (StringUtils.isBlank(currPerm.getDatasourceId())) {
        continue;
      }

      this.mapper.deletePermByCond(currPerm.getRoleId(), currPerm.getDatasourceId(), orgId);
    }

    String logTitle = "移除数据源授权：【" + JSONObject.toJSONString(permList) + "】";
    BdpLogUtil.log("数据源授权模块", logTitle, PlatformConstant.OpType.delete);
  }

  /**
   * 根据数据源ID删除权限(业务模块删除数据源时同步删除权限)
   *
   * @param datasourceId
   * @return
   */
  @Transactional
  public Integer deletePermById(String datasourceId) {
    if (StringUtils.isEmpty(datasourceId)) {
      return 0;
    }

    String orgId = ThreadContextHelper.getOrgId();
    if (StringUtils.isBlank(orgId)) {
      orgId = Constants.DEFAULT_ORG;
    }

    return this.mapper.deletePermByCond(null, datasourceId, orgId);
  }

  /**
   * 根据角色查询权限列表(提供给业务模块使用)
   *
   * @param roleId
   * @return
   */
  @Transactional
  public List<DatasourcePermDTO> getGrantedPermList(String roleId) {
    if (StringUtils.isNotEmpty(roleId)) {
      return this.mapper.getGrantedPermList(roleId);
    }

    return new ArrayList<>();
  }

  /**
   * 新增权限时合法性检查
   *
   * @param permList
   */
  private void checkAddDatsourcePermValidity(List<DatasourcePermDTO> permList) {
    if (CollectionUtils.isEmpty(permList)) {
      throw new BusinessException("未选择待授权数据源.");
    }

    for (DatasourcePermDTO currPerm : permList) {
      if (currPerm != null) {
        CheckParaUtils.checkStringValidity(currPerm.getRoleId(), logger, "角色ID为空");
        CheckParaUtils.checkStringValidity(currPerm.getDatasourceId(), logger, "数据源ID为空");
        CheckParaUtils.checkObjectValidity(currPerm.getAction(), logger, "权限不能为空");
        if (currPerm.getAction() != null && !currPerm.getAction().equals(Constants.QUERY_ACTION)) {
          throw new BusinessException("权限范围[0], 当前值为：" + currPerm.getAction());
        }
      }
    }
  }

  /**
   * 批量构建权限
   *
   * @param permList
   * @return
   */
  private List<DatasourcePermDTO> batchBuildPerm(List<DatasourcePermDTO> permList) {
    List<DatasourcePermDTO> permDTOList = Lists.newArrayList();
    for (DatasourcePermDTO currPerm : permList) {
      if (currPerm != null) {
        DatasourcePermDTO permDTO =
            buildDatasourcePerm(
                currPerm.getRoleId(), currPerm.getDatasourceId(), currPerm.getAction());

        permDTOList.add(permDTO);
      }
    }

    return permDTOList;
  }

  /**
   * 构建权限
   *
   * @param roleId
   * @param datasourceId
   * @param action
   * @return
   */
  private DatasourcePermDTO buildDatasourcePerm(
      String roleId, String datasourceId, Integer action) {
    // 取消授权时，action为null
    if (action == null) {
      return null;
    }

    // 根据datasourceId获取数据源信息
    DataSourceDTO dataSourceDTO = this.dataSourceService.queryDataSourceById(datasourceId);

    // 构建权限
    DatasourcePermDTO newDto = new DatasourcePermDTO();
    newDto.setId(ComUtil.getId());
    newDto.setName(dataSourceDTO.getDatasourceName());
    newDto.setRoleId(roleId);
    newDto.setDatasourceId(datasourceId);
    newDto.setDatasourceName(dataSourceDTO.getDatasourceName());
    newDto.setEffect(Constants.EFFECT_ALLOW);
    newDto.setDimension(Constants.DIMENSION_ROLE);
    newDto.setAction(action);
    newDto.setRelated(Constants.NOT_RELATED_PERM);

    // 批量删除时不会自动填充创建者等信息，此处需要特殊处理
    PojoUtil.setSysProperties(newDto, PlatformConstant.OpType.insert);

    return newDto;
  }
}
